package table

import (
	"errors"

	"gitee.com/dingiyan/goMyAdmin/db"
	"gorm.io/gorm"
)

// AddRelationshipInput 定义传入的参数结构
type AddRelationshipInput struct {
	Name          string `json:"name" binding:"required"`         // 关系名称
	DatasourceID  uint   `json:"datasourceId" binding:"required"` // 数据源ID
	Database      string `json:"database" binding:"required"`     // 数据库
	SourceTable   string `json:"sourceTable" binding:"required"`  // 源表名
	TargetTable   string `json:"targetTable" binding:"required"`  // 目标表名
	Type          string `json:"type" binding:"required"`         // 关系类型（object/array）
	Relationships []struct {
		SourceTableField string `json:"sourceTableField" binding:"required"` // 源表字段名
		TargetTableField string `json:"targetTableField" binding:"required"` // 目标表字段名
	} `json:"relationships" binding:"required"` // 字段关联列表
}

// AddRelationship 新增关联关系
func AddRelationship(input AddRelationshipInput) error {
	// 校验关联关系列表数量
	if len(input.Relationships) == 0 {
		return errors.New("关联关系列表数量必须大于0")
	}

	// 开始事务
	tx := db.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
			panic(r)
		}
	}()

	// 创建 TableRelationship 实体
	tableRelationship := db.TableRelationship{
		Name:             input.Name,
		Database:         input.Database,
		DatasourceID:     input.DatasourceID,
		SourceTable:      input.SourceTable,
		TargetTable:      input.TargetTable,
		RelationshipType: input.Type,
	}

	// 插入主表记录
	if err := tx.Create(&tableRelationship).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 批量插入关联字段
	var fields []db.TableRelationshipField
	for _, relationship := range input.Relationships {
		field := db.TableRelationshipField{
			RelationshipID:              tableRelationship.ID,
			SourceTableField:            relationship.SourceTableField,
			TargetTableField:            relationship.TargetTableField,
			SourceTargetRelationshipKey: input.Name, // 作为关系名称的标识
		}
		fields = append(fields, field)
	}

	if err := tx.Create(&fields).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 提交事务
	tx.Commit()
	return nil
}

// UpdateRelationshipInput 定义传入的参数结构
type UpdateRelationshipInput struct {
	ID            uint `json:"id" binding:"required"` // 关系ID
	Relationships []struct {
		ID               *uint  `json:"id"`               // 字段关系ID（可选，存在则更新，不存在则新增）
		SourceTableField string `json:"sourceTableField"` // 源表字段名
		TargetTableField string `json:"targetTableField"` // 目标表字段名
	} `json:"relationships" binding:"required"` // 字段关联列表
}

// UpdateRelationship 更新关联关系
func UpdateRelationship(input UpdateRelationshipInput) error {
	// 校验关联关系列表数量
	if len(input.Relationships) < 1 {
		return errors.New("关联关系列表数量必须大于1")
	}

	// 查询 TableRelationship 是否存在
	var tableRelationship db.TableRelationship
	if err := db.DB.First(&tableRelationship, input.ID).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("不存在此关联关系")
		}
		return err
	}

	// 开始事务
	tx := db.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
			panic(r)
		}
	}()

	// 获取当前关联关系的所有字段
	var existingFields []db.TableRelationshipField
	if err := tx.Where("relationship_id = ?", tableRelationship.ID).Find(&existingFields).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 记录需要保留的字段ID
	updatedFieldIDs := make(map[uint]bool)

	// 更新或新增字段关联
	for _, relationship := range input.Relationships {
		if relationship.ID != nil {
			// 更新已存在的字段关联
			var field db.TableRelationshipField
			if err := tx.First(&field, *relationship.ID).Error; err != nil {
				if errors.Is(err, gorm.ErrRecordNotFound) {
					tx.Rollback()
					return errors.New("指定的字段关联不存在")
				}
				tx.Rollback()
				return err
			}

			field.SourceTableField = relationship.SourceTableField
			field.TargetTableField = relationship.TargetTableField
			if err := tx.Save(&field).Error; err != nil {
				tx.Rollback()
				return err
			}
			updatedFieldIDs[field.ID] = true
		} else {
			// 新增字段关联
			field := db.TableRelationshipField{
				RelationshipID:   tableRelationship.ID,
				SourceTableField: relationship.SourceTableField,
				TargetTableField: relationship.TargetTableField,
			}
			if err := tx.Create(&field).Error; err != nil {
				tx.Rollback()
				return err
			}
			updatedFieldIDs[field.ID] = true
		}
	}

	// 删除不在更新数据中的字段关联
	for _, field := range existingFields {
		if _, exists := updatedFieldIDs[field.ID]; !exists {
			if err := tx.Delete(&field).Error; err != nil {
				tx.Rollback()
				return err
			}
		}
	}

	// 提交事务
	tx.Commit()
	return nil
}

// DeleteRelationshipInput 定义删除传入的参数结构
type DeleteRelationshipInput struct {
	DsID uint `json:"dsId" binding:"required"` // 数据源ID
	ID   uint `json:"id" binding:"required"`   // 关系ID
}

// DeleteRelationship 删除关联关系
func DeleteRelationship(input DeleteRelationshipInput) error {
	// 查询 TableRelationship 是否存在
	var tableRelationship db.TableRelationship
	if err := db.DB.Where("id = ? AND datasource_id = ?", input.ID, input.DsID).First(&tableRelationship).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("不存在此关联关系")
		}
		return err
	}

	// 开始事务
	tx := db.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
			panic(r)
		}
	}()

	// 删除关联的字段关系
	if err := tx.Where("relationship_id = ?", input.ID).Delete(&db.TableRelationshipField{}).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 删除主关系
	if err := tx.Delete(&tableRelationship).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 提交事务
	tx.Commit()
	return nil
}

// QueryRelationshipInput 定义查询关联关系的输入参数
type QueryRelationshipInput struct {
	DsID     uint   `json:"dsId" binding:"required"`     // 数据源ID
	Database string `json:"database" binding:"required"` // 数据库
	Table    string `json:"table" binding:"required"`    // 表名
}

// RelationshipOutput 定义返回的关联关系结构
type RelationshipOutput struct {
	ID            uint   `json:"id"`          // 关系ID
	Name          string `json:"name"`        // 关系名称
	Database      string `json:"database"`    // 数据库
	SourceTable   string `json:"sourceTable"` // 源表
	TargetTable   string `json:"targetTable"` // 目标表
	Type          string `json:"type"`        // 关系类型 (object, array)
	Relationships []struct {
		ID               uint   `json:"id"`
		SourceTableField string `json:"sourceTableField"` // 源表字段
		TargetTableField string `json:"targetTableField"` // 目标表字段
	} `json:"relationships"` // 字段关系
}

// QueryTableRelationships 查询关联关系列表
func QueryTableRelationships(input QueryRelationshipInput) ([]RelationshipOutput, error) {
	var relationships []db.TableRelationship

	// 查询 TableRelationship 表中匹配条件的记录
	err := db.DB.Where("datasource_id = ? and database = ? and source_table = ?", input.DsID, input.Database, input.Table).
		Find(&relationships).Error
	if err != nil {
		return nil, err
	}

	// 查询对应的字段关系并构造返回结果
	var results []RelationshipOutput
	for _, relationship := range relationships {
		var fields []db.TableRelationshipField
		err := db.DB.Where("relationship_id = ?", relationship.ID).Find(&fields).Error
		if err != nil {
			return nil, err
		}

		// 构造输出格式
		output := RelationshipOutput{
			ID:          relationship.ID,
			Name:        relationship.Name,
			Database:    relationship.Database,
			SourceTable: relationship.SourceTable,
			TargetTable: relationship.TargetTable,
			Type:        relationship.RelationshipType,
		}

		for _, field := range fields {
			output.Relationships = append(output.Relationships, struct {
				ID               uint   `json:"id"`
				SourceTableField string `json:"sourceTableField"`
				TargetTableField string `json:"targetTableField"`
			}{
				ID:               field.ID,
				SourceTableField: field.SourceTableField,
				TargetTableField: field.TargetTableField,
			})
		}

		results = append(results, output)
	}

	return results, nil
}
